package com.songyang.yougnsql.core.data.pagecache;

import com.songyang.yougnsql.common.ErrorMsg;
import com.songyang.yougnsql.common.ExceptionHandler;
import com.songyang.yougnsql.common.YoungSQLException;
import com.songyang.yougnsql.core.data.page.Page;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;

public interface PageCache {

    static Boolean create(String path, long memory) {
        File f = new File(path +File.separator+"YoungSQL"+ PageCacheImpl.DB_SUFFIX);
        try {
            if (!f.createNewFile()) {
                throw new YoungSQLException(ErrorMsg.FILE_EXISTS_EXCEPTION);
            }
            return true;
        } catch (YoungSQLException | IOException e) {
            ExceptionHandler.handler(e);
            return false;
        }
    }

    /**
     * 打开一个数据库文件
     *
     * @param path   数据库的地址
     * @param memory 要打开的页面数量
     * @return PageCacheImpl
     * @throws YoungSQLException 异常
     */
    static PageCacheImpl open(String path, long memory) throws YoungSQLException {
        File f = new File(path + File.separator+"YoungSQL"+PageCacheImpl.DB_SUFFIX);
        try {
            if (!f.exists()&& !create(path, memory)) {
                throw new YoungSQLException(ErrorMsg.FILE_CREATE_FAILED_EXCEPTION);
            }
            if (!f.canRead() || !f.canWrite()) {
                throw new YoungSQLException(ErrorMsg.FILE_CANNOT_RW_EXCEPTION);
            }
            RandomAccessFile randomAccessFile = new RandomAccessFile(f, "rw");
            FileChannel fileChannel = randomAccessFile.getChannel();
            return new PageCacheImpl(randomAccessFile, fileChannel, (int) memory / Page.PAGE_SIZE);
        } catch (YoungSQLException | FileNotFoundException e) {
            ExceptionHandler.handler(e);
        }
        throw new YoungSQLException(ErrorMsg.CREATE_PAGE_CACHE_FAILED);
    }

    int newPage(byte[] initData);

    Page getPage(int pageNumber) throws Exception;

    void close();

    void release(Page page);

    void truncateByPageNumber(int maxPageNmber);

    int getPageNumber();

    void flushPage(Page pg);
}
